import torch
import torch.nn as nn
import torch.optim as optim

# unsqueeze() 的作用是在指定位置添加一个维度，将张量的维度数增加1。
# 具体说明：
# 功能：在指定的维度索引位置插入一个大小为1的新维度
# 参数：接受一个整数参数，表示要添加维度的位置索引
# 示例效果：
# 原始张量：[1, 2, 3] 形状为 (3,)
# 执行 unsqueeze(1) 后：[[1], [2], [3]] 形状变为 (3, 1)
# 这将一维向量转换为二维列向量矩阵
# 在您的代码中，unsqueeze(1) 将一维张量转换为二维张量，使数据更适合神经网络的批量处理要求。
x = torch.tensor([1.0, 2.0, 3.0])
y = torch.tensor([6.0, 17.0, 34.0])

print(x)
print(y)

x = torch.tensor([1.0, 2.0, 3.0]).unsqueeze(1)
y = torch.tensor([6.0, 17.0, 34.0]).unsqueeze(1)

print(x)
print(y)

# dim 参数的取值和含义
# dim 参数用于指定张量的维度索引，其取值范围和含义如下：
# 取值范围
# 对于 n 维张量，dim 可以取 -n 到 n-1 的整数值
# 常用范围：0 到 n-1（正索引）
# 各维度含义
# 对于形状为 (3, 1) 的张量 x：
# dim=0：行维度，沿第0维（行）进行操作
# dim=1：列维度，沿第1维（列）进行操作
phi = torch.cat([x ** 2, x], dim=1)

print(phi)

# nn.Linear(2, 1, bias=True)：构建一个全连接层
# 输入维度为2，输出维度为1
# bias=True表示包含偏置项
# 该层会学习权重矩阵和偏置向量，用于线性变换输入数据
model = nn.Linear(2, 1, bias=True)

criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=1e-2)

for epoch in range(100):
    optimizer.zero_grad()
    y_pred = model(phi)
    loss = criterion(y_pred, y)
    loss.backward()
    optimizer.step()

x4 = torch.tensor([[4.0]])
phi4 = torch.cat([x4 ** 2, x4], dim=1)
print(model(phi4).item())

w = model.weight.data.squeeze()
b = model.bias.data.item()
print(w, b)
